home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 June: Reference Library / Dev.CD Jun 99 RL Disk 1.toast / What's New / Development Kits / Mac_OS_USB_DDK_v1.2 / Examples / CompositeClassDriver / CompositeClassDriver.c next >
Encoding:
C/C++ Source or Header  |  1999-04-15  |  9.1 KB  |  245 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CompositeClassDriver.c
  3.  
  4.     Contains:    Core functionality to Composite Class Driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "CompositeClassDriver.h"
  19. extern    usbCompositePBStruct myCompositePBRecord;
  20.  
  21.  
  22. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  23. {
  24.     paramblock->usbReference = theDeviceRef;
  25.     paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  26.     paramblock->pbLength = sizeof(usbCompositePBStruct);
  27.     paramblock->pbVersion = kUSBCurrentPBVersion;
  28.     paramblock->usb.cntl.WIndex = 0;             
  29.     paramblock->usbBuffer = nil;        
  30.     paramblock->usbStatus = kUSBNoErr;
  31.     paramblock->usbReqCount = 0;
  32.     paramblock->usbActCount = 0;
  33.     paramblock->usb.cntl.WValue = 0;
  34.     paramblock->usbFlags = 0;
  35. }
  36.  
  37.  
  38. Boolean immediateError(OSStatus err)
  39. {
  40.     return((err != kUSBPending) && (err != kUSBNoErr) );
  41. }
  42.  
  43. void CompositeDeviceInitiateTransaction(USBPB *pb)
  44. {
  45. register usbCompositePBStruct *pCompositePB;
  46. OSStatus myErr;
  47.  
  48.     pCompositePB = (usbCompositePBStruct *)(pb);
  49.  
  50.     if (pCompositePB->expertTerminatePending)                // TCC <USB16>
  51.         return;
  52.         
  53.     pCompositePB->transDepth++;
  54.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  55.     {
  56.     
  57.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Illegal Transaction Depth", pCompositePB->pb.usbRefcon);
  58.     }
  59.     
  60.     if (pCompositePB->driverRemovalPending)
  61.     {
  62.         pCompositePB->pb.usbRefcon = kReturnFromDriver;
  63.         return;
  64.     }
  65.  
  66.     switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction)
  67.     {
  68.         case kGetFullConfiguration0:
  69.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  70.             pCompositePB->pb.usb.cntl.WIndex = 0;             
  71.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  72.             
  73.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  74.             myErr = USBGetFullConfigurationDescriptor(pb);
  75.             if(immediateError(myErr))
  76.             {
  77.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration (#1) - immediate error", myErr);
  78.             }
  79.             break;
  80.         
  81.         case kSetConfig:
  82.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  83.             pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);
  84.             
  85.             pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetConfig;
  86.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->pFullConfigDescriptor->configValue;         /* Use configuration ID value from descriptor */
  87.             
  88.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  89.             
  90.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  91.             myErr = USBDeviceRequest(pb);
  92.             if(immediateError(myErr))
  93.             {
  94.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kSetConfig - immediate error", myErr);
  95.             }
  96.             break;
  97.             
  98.         case kNewInterfaceRef:
  99.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  100.             // Note: pCompositePB->usb.cntl.WIndex will be set to zero by InitParamBlock
  101.             // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef
  102.             pCompositePB->pb.usb.cntl.WIndex = pCompositePB->interfaceIndex;
  103.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  104.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  105.  
  106.             myErr = USBNewInterfaceRef(pb);
  107.             if(immediateError(myErr))
  108.             {
  109.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kNewInterfaceRef - immediate error", myErr);
  110.             }
  111.             break;
  112.             
  113.         default:
  114.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon);
  115.             pCompositePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  116.             break;
  117.     }
  118.     
  119. // At this point the control is returned to the system.  If a USB transaction
  120. // has been initiated, then it will call the Complete procs
  121. // (below) to handle the results of the transaction.
  122. }
  123.  
  124. void CompositeDeviceCompletionProc(USBPB *pb)
  125. {
  126. OSStatus myErr;
  127. register usbCompositePBStruct *pCompositePB;
  128. USBInterfaceDescriptorPtr pInterfaceDescriptor;
  129. UInt32 i;
  130.  
  131.     pCompositePB = (usbCompositePBStruct *)(pb);
  132.  
  133.     if (pCompositePB->expertTerminatePending)                // TCC <USB16>
  134.         return;
  135.         
  136.     pCompositePB->transDepth--;
  137.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  138.     {
  139.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Illegal Transaction Depth", pCompositePB->transDepth);
  140.     }
  141.     
  142.     if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending))
  143.     {
  144.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Completion Error", pCompositePB->pb.usbStatus);
  145.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  146.         pCompositePB->pb.usbRefcon |= kRetryTransaction;
  147.         pCompositePB->retryCount--;
  148.         if (!pCompositePB->retryCount)
  149.         {
  150.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Too many retries", pCompositePB->pb.usbRefcon);
  151.             pCompositePB->pb.usbRefcon = kReturnFromDriver;
  152.             return;
  153.         }
  154.     }
  155.     else
  156.     {
  157.         pCompositePB->pb.usbRefcon &= ~kRetryTransaction;
  158.         pCompositePB->retryCount = kCompositeRetryCount;
  159.     }
  160.  
  161.     if (pCompositePB->pb.usbRefcon & kCompletionPending)             
  162.     {                                                
  163.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  164.         switch(pCompositePB->pb.usbRefcon)
  165.         {
  166.             case kGetFullConfiguration0:
  167.                 pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer;
  168.                 if (pCompositePB->pFullConfigDescriptor == nil)
  169.                 {
  170.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon);
  171.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  172.                     break;
  173.                 }
  174.                 
  175.                 BlockCopy(   (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) )  );
  176.                 USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName" - Configuration->maxPower = ", pCompositePB->pFullConfigDescriptor->maxPower);
  177.                 USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName" -      Hub supplied power = ", pCompositePB->busPowerAvailable);
  178.                 if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable)
  179.                 {
  180.                     pCompositePB->pb.usbRefcon = kSetConfig;
  181.                 }
  182.                 else
  183.                 {
  184.                     USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower);
  185.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, kCompositeDriverName" - Insufficient power for device", pCompositePB->busPowerAvailable);
  186.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  187.                 }
  188.                 break;
  189.                 
  190.             case kSetConfig:            /* get all the interface descriptors and save them */
  191.                 for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++)
  192.                 {
  193.                     pCompositePB->interfaceRefArray[i] = 0;
  194.                     myErr = GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor);
  195.                     if (kUSBNoErr == myErr)
  196.                     {
  197.                         BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length));
  198.                     }
  199.                     else                /* if GetInterfaceDescriptor returned an error, then set the length to zero (so we know later) */
  200.                     {
  201.                         pCompositePB->interfaceDescriptors[i].length = 0;
  202.                     }
  203.                 }
  204.                 pCompositePB->interfaceIndex = 0;
  205.                 pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces;
  206.                 pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  207.                 break;
  208.                 
  209.             case kNewInterfaceRef:
  210.                 /* save the new interface ref for this interface */
  211.                 pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference;
  212.                 
  213.                 /* only install the interface driver if we had a valid interface descriptor */
  214.                 if (pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex].length != 0)
  215.                 {
  216.                     USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0);
  217.                 }
  218.                 
  219.                 /* advance to the next interface */
  220.                 pCompositePB->interfaceIndex++;
  221.                 
  222.                 /* if there's more interfaces, then just keep cycling through kNewInterfaceRef */
  223.                 if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount)
  224.                 {
  225.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  226.                 }
  227.                 else
  228.                 {
  229.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  230.                 }
  231.                 break;
  232.             
  233.             default:
  234.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon);
  235.                 pCompositePB->pb.usbRefcon = kReturnFromDriver;
  236.                 break;
  237.         }
  238.     }
  239.     if (!(pCompositePB->pb.usbRefcon & kReturnFromDriver) && (!pCompositePB->driverRemovalPending))
  240.         CompositeDeviceInitiateTransaction(pb);
  241.  
  242. }
  243.  
  244.  
  245.